import json
import os.path

from PySide6.QtGui import QKeySequence, QShortcut, QAction
from PySide6.QtWidgets import QMainWindow, QMessageBox, QTreeWidgetItem, QTreeWidget, QMenu, QInputDialog, QLineEdit, \
    QHeaderView, QPushButton, QWidget, QTabWidget
from PySide6.QtUiTools import QUiLoader
from PySide6.QtCore import Qt, QPoint, QMargins
from global_variables import GlobalVariables
from util import common


class FavConnection(QMainWindow):

    def __init__(self, app):
        super().__init__()
        self.app = app
        self.ui = app.ui

        self.config_path = GlobalVariables.PROJECT_BASE_PATH + 'connection.json'

        # 载入配置
        self.tree_init()
        # 定义连接信号
        self.connect_func()

    def connect_func(self):
        self.ui.add_fav_button.clicked.connect(self.add_fav_button_clicked)
        self.ui.proxy_add_fav_button.clicked.connect(self.add_fav_button_clicked)

        # 右键菜单
        self.ui.fav_connection.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.fav_connection.customContextMenuRequested.connect(self.show_menu)

        # 标签点击事件
        self.ui.fav_connection.itemClicked.connect(self.fav_connection_item_clicked)
        self.ui.fav_connection.itemDoubleClicked.connect(self.fav_connection_item_double_clicked)

        self.ui.quick_connect_button.clicked.connect(self.quick_connect_button_clicked)


    def show_menu(self, point: QPoint):
        w: QTreeWidget = self.ui.fav_connection
        p: QWidget = w.parent()
        top_margin: float = p.layout().contentsMargins().top()
        menu = QMenu(w)

        item = self.ui.fav_connection.itemAt(point)

        point.setY(point.y() + 18)
        # 如果是空白，右键新增文件夹
        if item is None:
            common.add_action(menu, '新增文件夹', self.add_fav_connection_dir_clicked)
            desk_point = self.ui.fav_connection.mapToGlobal(point)
            menu.exec_(desk_point)
            return

        # 如果文件，显示删除
        if item.item_type == 'dir':
            common.add_action(menu, '重命名', self.rename_fav_connection_file_clicked)

        if item.item_type == 'file':
            common.add_action(menu, '复制一份', self.copy_fav_connection_file_clicked)

        common.add_action(menu, '删除', self.del_fav_connection_file_clicked)
        desk_point = self.ui.fav_connection.mapToGlobal(point)
        menu.exec_(desk_point)

    def tree_init(self):
        # # 设置自适应宽度
        # self.ui.fav_connection.header().setSectionResizeMode(QHeaderView.Stretch)
        # # 设置列最大宽度
        # self.ui.fav_connection.header().setMaximumSectionSize(200)
        # # 设置列最小宽度
        # self.ui.fav_connection.header().setMinimumSectionSize(30)

        # 初始化文件
        self.config_init()

    def config_init(self):
        if not os.path.exists(self.config_path):
            return

        with open(self.config_path, 'r') as f:
            content = f.read()
            if len(content) == 0:
                return
            dict_items = json.loads(content)
            for item in dict_items:
                subtree = self.add_subtree(QTreeWidgetItem(self.ui.fav_connection), item['item_type'], item)
                if item['item_type'] == 'file':
                    pass
                else:
                    for sub in item.get('sub', []):
                        self.add_subtree(QTreeWidgetItem(subtree), sub['item_type'], sub)

    def add_fav_button_clicked(self):
        sender: QPushButton = self.sender()
        parent = sender.parent()
        for child in parent.findChildren(QLineEdit):
            child: QLineEdit = child
            if child.objectName().endswith('connect_name') and len(child.text()) == 0:
                QMessageBox.information(self, '错误', '连接名称不能为空')
                return

        tree = self.ui.fav_connection
        selectedItems = tree.selectedItems()
        if len(selectedItems) == 0:
            # 一个都没有选中
            # 父级为根
            parent = tree
        elif len(selectedItems) == 1:
            # 判断是文件夹还是文件
            # 如果是文件，更新文件
            # 如果是文件夹，文件夹则父级
            if selectedItems[0].item_type == "file":
                self.add_subtree(selectedItems[0])
                # 禁用按钮
                self.ui.add_fav_button.setDisabled(True)
                self.save_connections()
                return
            else:
                parent = selectedItems[0]
        else:
            parent = tree

        # 如果链接名称存在
        if self.__connection_is_exists__(parent, self.ui.connect_name.text()):
            QMessageBox.information(self, '错误', '连接名称已存在，不能添加')
            return

        subtree = self.add_subtree(QTreeWidgetItem(parent))
        # 禁用按钮
        self.ui.add_fav_button.setDisabled(True)
        self.save_connections()

    def __connection_is_exists__(self, parent: QTreeWidget, text: str):
        if isinstance(parent, QTreeWidgetItem):
            for index in range(parent.childCount()):
                item = parent.child(index)
                if item.custom_data['connect_name'] == text:
                    return True

        if isinstance(parent, QTreeWidget):
            for index in range(parent.topLevelItemCount()):
                item = parent.topLevelItem(index)
                if item.custom_data['connect_tab'] == "tab_proxy":
                    return item.custom_data['proxy_connect_name'] == text
                elif item.custom_data['connect_tab'] == "tab_standard":
                    return item.custom_data['connect_name'] == text

        return False

    def add_subtree(self, subtree: QTreeWidgetItem, item_type: str = 'file', custom_data: dict = None):
        if custom_data is None:
            w: QTabWidget = self.ui.tabWidget
            current_widget = w.currentWidget()
            custom_data = {}
            connect_name = ""
            for child in current_widget.findChildren(QLineEdit):
                custom_data[child.objectName()] = child.text()
                if child.objectName().endswith('connect_name'):
                    connect_name = child.text()

            custom_data['connect_tab'] = current_widget.objectName()
            subtree.setText(0, connect_name)
            subtree.setToolTip(0, connect_name)
            subtree.item_type = item_type
            subtree.custom_data = custom_data
            return subtree

        connect_name = ""
        if 'connect_name' in custom_data['custom_data']:
            connect_name = custom_data['custom_data']['connect_name']
        elif 'proxy_connect_name' in custom_data['custom_data']:
            connect_name = custom_data['custom_data']['proxy_connect_name']
        subtree.setText(0, connect_name)
        subtree.setToolTip(0, connect_name)
        subtree.item_type = custom_data['item_type']
        if "connect_tab" not in custom_data['custom_data']:
            custom_data['custom_data']['connect_tab'] = "tab_standard"
        subtree.custom_data = custom_data['custom_data']

        if custom_data['custom_data']['connect_tab'] == "tab_standard":
            b: QPushButton = self.ui.test_connection_button
            b.setEnabled(True)
        elif custom_data['custom_data']['connect_tab'] == "tab_proxy":
            b: QPushButton = self.ui.proxy_test_connection_button
            b.setEnabled(True)
        return subtree

    def save_connections(self):
        tree = self.ui.fav_connection
        dict_items = []
        for index in range(tree.topLevelItemCount()):
            item = tree.topLevelItem(index)
            if item.item_type == 'file':
                dict_items.append({
                    'id': index,
                    'item_type': item.item_type,
                    'custom_data': item.custom_data,
                })
            else:
                sub = []
                for i in range(item.childCount()):
                    child = item.child(i)
                    sub.append({
                        'id': i,
                        'item_type': child.item_type,
                        'custom_data': child.custom_data,
                    })
                dict_items.append({
                    'id': index,
                    'item_type': item.item_type,
                    'custom_data': item.custom_data,
                    'sub': sub,
                })
        with open(self.config_path, 'w') as f:
            f.write(json.dumps(dict_items, ensure_ascii=False, indent=4))

    def copy_fav_connection_file_clicked(self):
        tree: QTreeWidget = self.ui.fav_connection
        selectedItems = tree.selectedItems()
        if len(selectedItems) != 1:
            return
        item: QTreeWidgetItem = selectedItems[0]
        custom_data = {
            "custom_data": item.custom_data.copy(),
            "item_type": item.item_type,
        }
        if 'connect_name' in custom_data['custom_data']:
            custom_data['custom_data']['connect_name'] += "@copy"
        elif 'proxy_connect_name' in custom_data['custom_data']:
            custom_data['custom_data']['proxy_connect_name'] += "@copy"
        self.add_subtree(QTreeWidgetItem(self.ui.fav_connection), 'file', custom_data)
        self.save_connections()

    def rename_fav_connection_file_clicked(self):
        text, okPressed = QInputDialog.getText(self.app, '重命名', '请输入新名称', QLineEdit.Normal, "")
        text = text.strip()
        if not okPressed or len(text) == 0:
            return
        tree = self.ui.fav_connection
        selectedItems = tree.selectedItems()
        if len(selectedItems) != 1:
            return
        item: QTreeWidgetItem = selectedItems[0]
        item.setText(0, text)
        item.setToolTip(0, text)
        if 'connect_name' in item.custom_data:
            item.custom_data['connect_name'] = text
        elif 'proxy_connect_name' in item.custom_data:
            item.custom_data['proxy_connect_name'] = text
        self.save_connections()

    def del_fav_connection_file_clicked(self):
        tree = self.ui.fav_connection
        selectedItems = tree.selectedItems()
        if len(selectedItems) == 1:
            if selectedItems[0].parent() is None:
                tree.takeTopLevelItem(tree.indexOfTopLevelItem(selectedItems[0]))
        self.save_connections()

    def add_fav_connection_dir_clicked(self):
        text, okPressed = QInputDialog.getText(self.app, '输入', '请输入目录名', QLineEdit.Normal, "")
        text = text.strip()
        if not okPressed or len(text) == 0:
            return
        tree = self.ui.fav_connection
        # 如果链接名称存在
        if self.__connection_is_exists__(tree, text):
            QMessageBox.information(self, '错误', '连接名称已存在，不能添加')
            return
        subtree = QTreeWidgetItem(tree)
        subtree.setText(0, text)
        subtree.setToolTip(0, text)
        subtree.item_type = 'dir'
        subtree.custom_data = {
            'connect_name': text
        }
        self.save_connections()

    def fav_connection_item_clicked(self, item, column):
        if item.item_type != 'file':
            return
        # todo 如果点击前选中与点击后选中的一样，那就不更新对应的VIEW

        connect_tab = item.custom_data.get('connect_tab')
        w: QTabWidget = self.ui.tabWidget
        if hasattr(self.ui, connect_tab):
            w.setCurrentWidget(getattr(self.ui, connect_tab))

        w: QTabWidget = self.ui.tabWidget
        for i in range(0, w.count()):
            for child in w.widget(i).findChildren(QLineEdit):
                child: QLineEdit = child
                child.clear()

        for k, v in item.custom_data.items():
            if k == "connect_tab":
                continue
            obj: QWidget = getattr(self.ui, k)
            if not isinstance(obj, QLineEdit):
                continue
            obj.setText(v)

    def fav_connection_item_double_clicked(self, item, column):
        if item.item_type == 'dir':
            pass
        elif item.item_type == 'file':
            if item.custom_data['connect_tab'] == "tab_standard":
                self.ui.connection_button.click()
                return
            if item.custom_data['connect_tab'] == "tab_proxy":
                self.ui.proxy_connection_button.click()

    def quick_connect_button_clicked(self):
        w: QTabWidget = self.ui.tabWidget
        for i in range(0, w.count()):
            for child in w.widget(i).findChildren(QLineEdit):
                child: QLineEdit = child
                child.clear()

        w.setCurrentIndex(0)
        self.ui.add_fav_button.setDisabled(True)
        self.ui.test_connection_button.setDisabled(True)

        self.ui.proxy_add_fav_button.setDisabled(True)
        self.ui.proxy_test_connection_button.setDisabled(True)